package org.liujing.jsw.host;

import java.util.*;
import java.util.logging.*;
import java.awt.image.*;
import java.awt.*;
import java.io.*;

public class BackgroundImageBoudler implements ImageConstants{
	private static Logger log = Logger.getLogger(BackgroundImageBoudler.class.getName());
	private String basePath = "";
	private int xRepeatImgWidth = 0;
	private int xRepeatImgHeight = 0;
	private int yRepeatImgWidth = 0;
	private int yRepeatImgHeight = 0;
	private java.util.List<File> xRepeatImgs = new ArrayList();
	private java.util.List<File> yRepeatImgs = new ArrayList();
	
	//private java.util.List<BImageGroup> imageGroups = new ArrayList();
	private BImageGroup xGroup;
	private BImageGroup yGroup;
	
	private String name;
	private OutputStream imageOut;
	
	public BackgroundImageBoudler(){
	}
	
	public BackgroundImageBoudler(String name){
		this.name = name;
		xGroup = new BImageGroup(X_REPEAT_TYPE, "x" + name);
		yGroup = new BImageGroup(Y_REPEAT_TYPE, "y" + name);
	}
	
	public BImage addImage(int imageType, String name, String path)throws IOException{
		BImage img = new BImage(imageType, name, path);
		if(imageType == X_REPEAT_TYPE){
			xGroup.addImage(img);
		}else{
			yGroup.addImage(img);
		}
		return img;
	}
	
	public boolean combineXImages(OutputStream stream)throws IOException{
		imageOut = stream;
		return xGroup.process();
	}
	
	public boolean combineYImages(OutputStream stream)throws IOException{
		imageOut = stream;
		return yGroup.process();
	}
	
	public static class BImage implements Serializable{
		public int type;
		public int width;
		public int height;
		private int x;
		private int y;
		public String name;
		public transient File file;
		private String path;
		
		public BImage(int imageType, String name, String path){
			type = imageType;
			this.name = name;
			//file = path;
			this.path = path;
		}
		
		public void calculate()throws IOException{
			InputStream in = BackgroundImageBoudler.class.getResourceAsStream(path);
			if(in == null){
				System.out.println("ERROR: image not found: " + path );
				throw new IOException("image not found: " + path);
			}
			BufferedImage image = javax.imageio.ImageIO.read(in);
			width = image.getWidth();
			height = image.getHeight();
			//log.info("width=" + width + ", height="+ height);
		}
		
		public File getFile(){
			return file;
		}
		
		public String getPath(){
			return path;
		}
		
		public int getWidth(){
			return width;
		}
		
		public int getHeight(){
			return height;
		}
		
		public int getX(){
			return x;
		}
		
		public int getY(){
			return y;
		}
		
		public void setX(int x){
			this.x = x;
		}
		
		public void setY(int y){
			this.y = y;
		}
		
		public boolean isRepeatX(){
			return type == X_REPEAT_TYPE;
		}
		
		public boolean isRepeatY(){
			return type == Y_REPEAT_TYPE;
		}
	}
	
	private class BImageGroup{
		public String id;
		public int type;
		public int width = 0;
		public int height = 0;
		private File targetFile;
		public java.util.List<BImage> images = new java.util.ArrayList();
		private boolean upToDate = true;
		private long lastModTime;
		
		public BImageGroup(int type, String id){
			this.type = type;
			this.id = id;
			targetFile = new File("_" + id + ".png");
			if(!targetFile.exists()){
				upToDate = false;
			}else{
				lastModTime = targetFile.lastModified();
			}
		}
		
		public void addImage(BImage image)throws IOException{
			image.calculate();
			if(type == Y_ROTATE_TYPE){
				height += image.getHeight();
				width = Math.max(width, image.getWidth());
			}else if(type == X_ROTATE_TYPE){
				width += image.getWidth();
				height = Math.max(height, image.getHeight());
			}
			images.add(image);
			//log.info(" added: width=" + width + ", height="+ height);
			//if(upToDate){
			//	upToDate = image.getFile().lastModified() <= lastModTime;
			//	if(!upToDate)
			//		System.out.println(image.getFile().getName() + " is up to date");
			//}
		}
		
		public boolean process()throws IOException{
			//if(upToDate){
			//	return false;
			//}
			if(images.size() == 0)
				return false;
			//log.info(" #final size: width=" + width + ", height="+ height);
			BufferedImage bundleImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
			Graphics2D g = bundleImage.createGraphics();
			if(type == Y_ROTATE_TYPE){
				int y = 0;
				for(BImage bImage : images){
					BufferedImage image = javax.imageio.ImageIO.read(BackgroundImageBoudler.class.getResourceAsStream(bImage.getPath()));
					g.drawImage(image, 0, y, null);
					bImage.setX(0);
					bImage.setY(y);
					y += image.getHeight();
				}
			}else if(type == X_ROTATE_TYPE){
				int x = 0;
				for(BImage bImage : images){
					BufferedImage image = javax.imageio.ImageIO.read(BackgroundImageBoudler.class.getResourceAsStream(bImage.getPath()));
					g.drawImage(image, x, 0, null);
					bImage.setX(x);
					bImage.setY(0);
					x += image.getWidth();
				}
			}
			g.dispose();
			javax.imageio.ImageIO.write(bundleImage, "png", imageOut);
			return true;
		}
	}
	
	
	public void addXRepeatImage(File path){
		xRepeatImgs.add(path);
	}
	
	public void addYRepeatImage(File path){
		yRepeatImgs.add(path);
	}
	
	private void perform()throws IOException{
		for(File path : xRepeatImgs){
			BufferedImage image = javax.imageio.ImageIO.read(
				path
			);
			xRepeatImgHeight += image.getHeight();
			xRepeatImgWidth = Math.max(xRepeatImgWidth, image.getWidth());
		}
		
		for(File path : yRepeatImgs){
			BufferedImage image = javax.imageio.ImageIO.read(
				path
			);
			yRepeatImgHeight = Math.max(yRepeatImgHeight, image.getHeight());
			yRepeatImgWidth += image.getWidth();
		}
		if(log.isLoggable(Level.INFO)){
			//log.info("x-repeat width=" + xRepeatImgWidth + " height="+ xRepeatImgHeight);
			//log.info("y-repeat width=" + yRepeatImgWidth + " height="+ yRepeatImgHeight);
		}
		
		BufferedImage xRepeatImg = new BufferedImage(xRepeatImgWidth, xRepeatImgHeight, BufferedImage.TYPE_4BYTE_ABGR);
		Graphics2D g = xRepeatImg.createGraphics();
		int y = 0;
		for(File path : xRepeatImgs){
			BufferedImage image = javax.imageio.ImageIO.read(path);
			g.drawImage(image, 0, y, null);
			y += image.getHeight();
		}
		javax.imageio.ImageIO.write(xRepeatImg,"png", new File("xRepeatBackImage.png"));
	}
	
	public void bundleImages(File directory)throws IOException{
		File[] images = directory.listFiles();
		for(File imageFile : images){
			String name = imageFile.getName();
			if(!name.endsWith(".png") && !name.endsWith(".jpg") && !name.endsWith(".gif")){
				continue;
			}
			addXRepeatImage(imageFile);
		}
		perform();
	}
	
	public static void main(String[] args)throws Exception{
		String[] formatNames = javax.imageio.ImageIO.getWriterFormatNames();
		for(String name : formatNames){
			System.out.println(name);
		}
		//BMP
		//bmp
		//jpg
		//JPG
		//jpeg
		//wbmp
		//png
		//JPEG
		//PNG
		//WBMP
		//GIF
		//gif
		if(args.length>0){
			BackgroundImageBoudler boudler = new BackgroundImageBoudler();
			boudler.bundleImages(new File(args[0]));
		}
	}
}